home *** CD-ROM | disk | FTP | other *** search
/ Internet Publisher's Toolbox 2.0 / Internet Publisher's Toolbox.iso / internet / ntserver / wtsource / zutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-08  |  23.8 KB  |  1,052 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE:
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.  
  4. */
  5.  
  6. /* Copyright (c) CNIDR (see ../COPYRIGHT) */
  7.  
  8. #ifndef lint
  9. static char *RCSid = "$Header: /usr/users/freewais/FreeWAIS-0.1/ir/zutil.c,v 1.1 1993/02/16 15:05:35 freewais Exp $";
  10. #endif
  11.  
  12. /* Change log:
  13.  * $Log: zutil.c,v $
  14.  * Revision 1.1  1993/02/16  15:05:35  freewais
  15.  * Initial revision
  16.  *
  17.  * Revision 1.6  92/03/26  18:27:16  jonathan
  18.  * Fixed function declaration.
  19.  * 
  20.  * Revision 1.5  92/03/07  19:41:14  jonathan
  21.  * ANSIfied argument list.
  22.  * 
  23.  * Revision 1.4  92/02/12  14:01:37  jonathan
  24.  * Added "$Log" so RCS will put the log message in the header
  25.  * 
  26.  *
  27.    3.26.90      Harry Morris, morris@think.com
  28.    3.30.90  Harry Morris - Changed any->bits to any->bytes
  29.    4.11.90  HWM - fixed include file names, changed 
  30.                                 - writeCompressedIntegerWithPadding() to
  31.                   writeCompressedIntWithPadding()
  32.                 - generalized conditional includes (see c-dialect.h)
  33.    3.7.91   Jonny Goldman.  Replaced "short" in makeBitMap with "int" line 632.
  34. */
  35.  
  36. #define _C_utils_Z39_50_
  37.  
  38. #include "zutil.h"
  39.  
  40. #include <math.h>
  41. #include <string.h>
  42.  
  43. char* readErrorPosition = NULL; /* pos where buf stoped making sense */
  44.  
  45. /*----------------------------------------------------------------------*/
  46. /* A note on error handling 
  47.    read - these are low level routines, they do not check the type tags
  48.    which (sometimes) preceed the data (this is done by the higher
  49.    level functions which call these functions).  There is no 
  50.    attempt made to check that the reading does not exceed the read
  51.    buffer.  Such cases should be very rare and usually will be 
  52.    caught by the calling functions. (note - it is unlikely that 
  53.    a series of low level reads will go far off the edge without
  54.    triggering a type error.  However, it is possible for a single
  55.    bad read in an array function (eg. readAny) to attempt to read a 
  56.    large ammount, possibly causing a segmentation violation or out
  57.    of memory condition.
  58.  */
  59. /*----------------------------------------------------------------------*/
  60.  
  61. diagnosticRecord* 
  62. makeDiag(surrogate,code,addInfo)
  63. boolean surrogate;
  64. char* code;
  65. char* addInfo;
  66. {
  67.   diagnosticRecord* diag = 
  68.     (diagnosticRecord*)s_malloc((size_t)sizeof(diagnosticRecord));
  69.   
  70.   diag->SURROGATE = surrogate;
  71.   memcpy(diag->DIAG,code,DIAGNOSTIC_CODE_SIZE);
  72.   diag->ADDINFO = s_strdup(addInfo); 
  73.  
  74.   return(diag);
  75. }
  76.  
  77. /*----------------------------------------------------------------------*/
  78.  
  79. void 
  80. freeDiag(diag)
  81. diagnosticRecord* diag;
  82.   if (diag != NULL)
  83.     { if (diag->ADDINFO != NULL)
  84.         s_free(diag->ADDINFO);
  85.         s_free(diag);
  86.       }
  87. }
  88.  
  89. /*----------------------------------------------------------------------*/
  90.  
  91. #define END_OF_RECORD   0x1D
  92.  
  93. char* 
  94. writeDiag(diag,buffer,len)
  95. diagnosticRecord* diag;
  96. char* buffer;
  97. long* len;
  98. /* diagnostics (as per Appendix D) have a very weird format - this changes
  99.    in SR-1
  100.  */
  101. {
  102.   char* buf = buffer;
  103.   long  length;
  104.   
  105.   if (diag == NULL)             /* handle unspecified optional args */
  106.     return(buf);
  107.  
  108.   buf = writeTag(DT_DatabaseDiagnosticRecords,buf,len);
  109.   CHECK_FOR_SPACE_LEFT(0L,len);
  110.   
  111.   length = 3; 
  112.   if (diag->ADDINFO != NULL)
  113.     length += strlen(diag->ADDINFO);
  114.     
  115.   if (length >= 0xFFFF )        /* make sure the length is reasonable */
  116.     { length = 0xFFFF - 1;
  117.       diag->ADDINFO[0xFFFF - 3 - 1] = '\0';
  118.     }
  119.    
  120.   buf = writeBinaryInteger(length,2L,buf,len);
  121.  
  122.   CHECK_FOR_SPACE_LEFT(1L,len);
  123.   buf[0] = diag->DIAG[0]; 
  124.   buf++;
  125.   
  126.   CHECK_FOR_SPACE_LEFT(1L,len);
  127.   buf[0] = diag->DIAG[1];
  128.   buf++;
  129.   
  130.   if (length > 3)
  131.     { CHECK_FOR_SPACE_LEFT(3L,len);
  132.       memcpy(buf,diag->ADDINFO,(size_t)length - 3);
  133.       buf += length - 3;
  134.     }
  135.    
  136.   CHECK_FOR_SPACE_LEFT(1L,len);
  137. #ifdef WIN32
  138.   buf[0] = (char)(diag->SURROGATE);
  139. #else
  140.   buf[0] = diag->SURROGATE;
  141. #endif
  142.   buf++;
  143.   
  144.   CHECK_FOR_SPACE_LEFT(1L,len);
  145.   buf[0] = END_OF_RECORD;
  146.   buf++;
  147.  
  148.   return(buf);
  149. }
  150.  
  151. /*----------------------------------------------------------------------*/
  152.  
  153. char* 
  154. readDiag(diag,buffer)
  155. diagnosticRecord** diag;
  156. char* buffer;
  157. {
  158.   char* buf = buffer;
  159.   diagnosticRecord* d 
  160.     = (diagnosticRecord*)s_malloc((size_t)sizeof(diagnosticRecord));
  161.   data_tag tag;
  162.   long len;
  163.   
  164.   buf = readTag(&tag,buf);
  165.   
  166.   buf = readBinaryInteger(&len,2L,buf);
  167.   
  168.   d->DIAG[0] = buf[0];
  169.   d->DIAG[1] = buf[1];
  170.   d->DIAG[2] = '\0';
  171.     
  172.   if (len > 3)
  173.     { d->ADDINFO = (char*)s_malloc((size_t)(len - 3 + 1));
  174.       memcpy(d->ADDINFO,(char*)(buf + 2),(size_t)(len - 3));
  175.       d->ADDINFO[len - 3] = '\0';
  176.     }
  177.   else
  178.     d->ADDINFO = NULL;
  179.     
  180.   d->SURROGATE = buf[len - 1];
  181.   
  182.   *diag = d;
  183.  
  184.   return(buf + len + 1);
  185. }
  186.  
  187. /*----------------------------------------------------------------------*/
  188.  
  189. #define continueBit     0x80
  190. #define dataMask        0x7F
  191. #define dataBits        7
  192.  
  193. char*
  194. writeCompressedInteger(num,buf,len)
  195. unsigned long num;
  196. char* buf;
  197. long* len;
  198. /* write a binary integer in the format described on p. 40.
  199.    this might be sped up 
  200. */
  201. {
  202.   char byte;
  203.   long i;
  204.   unsigned long size;
  205.   
  206.   size = writtenCompressedIntSize(num);
  207. #ifdef WIN32
  208.   CHECK_FOR_SPACE_LEFT((long)size,len);
  209.   
  210.   for (i = size - 1; i >= 0; i--)
  211.     { byte = (char)(num & dataMask);
  212.       if (i != (long)(size-1))        /* turn on continue bit */
  213. #else
  214.   CHECK_FOR_SPACE_LEFT(size,len);
  215.   
  216.   for (i = size - 1; i >= 0; i--)
  217.     { byte = num & dataMask;
  218.       if (i != (size-1))        /* turn on continue bit */
  219. #endif
  220.         byte = (char)(byte | continueBit);
  221.       buf[i] = byte;
  222.       num = num >> dataBits;    /* don't and here */
  223.     }
  224.    
  225.   return(buf + size);
  226.  
  227. /*----------------------------------------------------------------------*/
  228.  
  229. char*
  230. readCompressedInteger(num,buf)
  231. unsigned long *num;
  232. char* buf;
  233. /* read a binary integer in the format described on p. 40.
  234.    this might be sped up 
  235. */
  236. {
  237.   long i = 0;
  238.   unsigned char byte;
  239.  
  240.   *num = 0;
  241.   
  242.   do 
  243.     { byte = buf[i++];
  244.       *num = *num << dataBits;
  245.       *num += (byte & dataMask);
  246.     }
  247.   while (byte & continueBit);
  248.  
  249.   return(buf + i);
  250.  
  251. /*----------------------------------------------------------------------*/
  252.  
  253. #define pad     128 /* high bit is set */
  254.  
  255. char*
  256. writeCompressedIntWithPadding(num,size,buffer,len)
  257. unsigned long num;
  258. unsigned long size;
  259. char* buffer;
  260. long* len;
  261. /* Like writeCompressedInteger, except writes padding (128) to make
  262.    sure that size bytes are used.  This can be read correctly by 
  263.    readCompressedInteger()
  264. */
  265. {
  266.   char* buf = buffer;
  267.   unsigned long needed,padding;
  268.   long i;
  269.     
  270. #ifdef WIN32
  271.   CHECK_FOR_SPACE_LEFT((long)size,len);
  272. #else
  273.   CHECK_FOR_SPACE_LEFT(size,len);
  274. #endif
  275.   
  276.   needed = writtenCompressedIntSize(num);
  277.   padding = size - needed;
  278.   i = padding - 1;
  279.  
  280.   for (i = padding - 1;i >= 0;i--)
  281. #ifdef WIN32
  282.     { buf[i] = (char)pad;
  283. #else
  284.     { buf[i] = pad;
  285. #endif
  286.     }
  287.   
  288.   buf = writeCompressedInteger(num,buf + padding,len);
  289.   
  290.   return(buf);
  291.  
  292. /*----------------------------------------------------------------------*/
  293.  
  294. unsigned long
  295. writtenCompressedIntSize(num)
  296. unsigned long num;
  297. /* return the number of bytes needed to represnet the value num in
  298.    compressed format.  curently limited to 4 bytes
  299.  */
  300. {
  301.   if (num < CompressedInt1Byte) 
  302.     return(1);
  303.   else if (num < CompressedInt2Byte) 
  304.     return(2);
  305.   else if (num < CompressedInt3Byte)
  306.     return(3);
  307.   else
  308.     return(4);    
  309. }
  310.  
  311. /*----------------------------------------------------------------------*/
  312.  
  313. char*
  314. writeTag(tag,buf,len)
  315. data_tag tag;
  316. char* buf;
  317. long* len;
  318. /* write out a data tag */
  319.   return(writeCompressedInteger(tag,buf,len));
  320.  
  321. /*----------------------------------------------------------------------*/
  322.  
  323. char*
  324. readTag(tag,buf)
  325. data_tag* tag;
  326. char* buf;
  327. /* read a data tag */
  328.   return(readCompressedInteger(tag,buf));
  329.  
  330. /*----------------------------------------------------------------------*/
  331.  
  332. unsigned long 
  333. writtenTagSize(tag)
  334. data_tag tag;
  335.   return(writtenCompressedIntSize(tag));
  336. }
  337.  
  338. /*----------------------------------------------------------------------*/
  339.  
  340. data_tag
  341. peekTag(buf)
  342. char* buf;
  343. /* read a data tag without advancing the buffer */
  344. {
  345.   data_tag tag;
  346.   readTag(&tag,buf);
  347.   return(tag);
  348.  
  349. /*----------------------------------------------------------------------*/
  350.  
  351. any* 
  352. makeAny(size,data)
  353. unsigned long size;
  354. char* data;
  355. {
  356.   any* a = (any*)s_malloc((size_t)sizeof(any));
  357.   a->size = size;
  358.   a->bytes = data;
  359.   return(a);
  360. }
  361.  
  362. /*----------------------------------------------------------------------*/
  363.  
  364. void
  365. freeAny(a)
  366. any* a;
  367. /* destroy an any and its associated data. Assumes a->bytes was
  368.    allocated using the s_malloc family of libraries 
  369.  */
  370. {
  371.   if (a != NULL)
  372.     { if (a->bytes != NULL)
  373.         s_free(a->bytes);
  374.       s_free(a);
  375.     }
  376. }
  377.  
  378. /*----------------------------------------------------------------------*/
  379.  
  380. any* 
  381. duplicateAny(a)
  382. any* a;
  383. {
  384.   any* copy = NULL;
  385.  
  386.   if (a == NULL)
  387.     return(NULL);
  388.  
  389.   copy = (any*)s_malloc((size_t)sizeof(any));
  390.   copy->size = a->size;
  391.   if (a->bytes == NULL)
  392.     copy->bytes = NULL;
  393.   else
  394.     { copy->bytes = (char*)s_malloc((size_t)copy->size);
  395.       memcpy(copy->bytes,a->bytes,(size_t)copy->size);
  396.     }
  397.   return(copy);
  398. }
  399.  
  400. /*----------------------------------------------------------------------*/
  401.  
  402. char* 
  403. writeAny(a,tag,buffer,len)
  404. any* a;
  405. data_tag tag;
  406. char* buffer;
  407. long* len;
  408. /* write an any + tag and size info */
  409. {
  410.   char* buf = buffer;
  411.  
  412.   if (a == NULL)                /* handle unspecified optional args */
  413.     return(buf);
  414.   
  415.   /* write the tags */
  416.   buf = writeTag(tag,buf,len);
  417.   buf = writeCompressedInteger(a->size,buf,len);
  418.  
  419.   /* write the bytes */
  420. #ifdef WIN32
  421.   CHECK_FOR_SPACE_LEFT((long)(a->size),len);
  422. #else
  423.   CHECK_FOR_SPACE_LEFT(a->size,len);
  424. #endif
  425.   memcpy(buf,a->bytes,(size_t)a->size);
  426.  
  427.   return(buf+a->size);
  428. }
  429.  
  430. /*----------------------------------------------------------------------*/
  431.  
  432. char* 
  433. readAny(anAny,buffer)
  434. any** anAny;
  435. char* buffer;
  436. /* read an any + tag and size info */
  437. {
  438.   char* buf = buffer;
  439.   any* a = (any*)s_malloc((size_t)sizeof(any));
  440.   data_tag tag;
  441.   
  442.   buf = readTag(&tag,buf);
  443.   buf = readCompressedInteger(&a->size,buf);
  444.   /* now simply copy the bytes */
  445.   a->bytes = (char*)s_malloc((size_t)a->size);
  446.   memcpy(a->bytes,buf,(size_t)a->size);
  447.   *anAny = a;
  448.   return(buf+a->size);
  449. }
  450.  
  451. /*----------------------------------------------------------------------*/
  452.  
  453. unsigned long 
  454. writtenAnySize(tag,a)
  455. data_tag tag;
  456. any* a;
  457. {
  458.   unsigned long size;
  459.  
  460.   if (a == NULL)
  461.     return(0);
  462.  
  463.   size = writtenTagSize(tag);
  464.   size += writtenCompressedIntSize(a->size);
  465.   size += a->size;
  466.   return(size);
  467. }
  468.  
  469. /*----------------------------------------------------------------------*/
  470.  
  471. any*
  472. stringToAny(s)
  473. char* s;
  474. {
  475.   any* a = NULL;
  476.   
  477.   if (s == NULL)
  478.     return(NULL);
  479.     
  480.   a = (any*)s_malloc((size_t)sizeof(any));
  481.   a->size = strlen(s);
  482.   a->bytes = (char*)s_malloc((size_t)a->size);
  483.   memcpy(a->bytes,s,(size_t)a->size);
  484.   return(a);
  485. }
  486.  
  487. /*----------------------------------------------------------------------*/
  488.  
  489. char*
  490. anyToString(a)
  491. any* a;
  492. {
  493.   char* s = NULL;
  494.   
  495.   if (a == NULL)
  496.     return(NULL);
  497.     
  498.   s = s_malloc((size_t)(a->size + 1));
  499.   memcpy(s,a->bytes,(size_t)a->size);
  500.   s[a->size] = '\0';
  501.   return(s);
  502. }
  503.  
  504. /*----------------------------------------------------------------------*/
  505.  
  506. char* 
  507. writeString(s,tag,buffer,len)
  508. char* s;
  509. data_tag tag;
  510. char* buffer;
  511. long* len;
  512. /* Write a C style string.  The terminating null is not written. 
  513.    This function is not part of the Z39.50 spec.  It is provided
  514.    for the convienience of those wishing to pass C strings in 
  515.    the place of an any.
  516.  */
  517. {
  518.   char* buf = buffer;
  519.   any* data = NULL;
  520.   if (s == NULL)
  521.     return(buffer);             /* handle unused optional item before making an any */
  522.   data = (any*)s_malloc((size_t)sizeof(any)); 
  523.   data->size = strlen(s);
  524.   data->bytes = s;              /* save a copy here by not using stringToAny() */
  525.   buf = writeAny(data,tag,buf,len);
  526.   s_free(data);                 /* don't use freeAny() since it will free s too */
  527.   return(buf);
  528. }
  529.  
  530. /*----------------------------------------------------------------------*/
  531.  
  532. char* 
  533. readString(s ,buffer)
  534. char** s ;
  535. char* buffer;
  536. /* Read an any and convert it into a C style string.
  537.    This function is not part of the Z39.50 spec.  It is provided
  538.    for the convienience of those wishing to pass C strings in 
  539.    the place of an any. 
  540.  */
  541. {
  542.   any* data = NULL;
  543.   char* buf = readAny(&data,buffer);
  544.   *s = anyToString(data);
  545.   freeAny(data);
  546.   return(buf);
  547. }
  548.  
  549. /*----------------------------------------------------------------------*/
  550.  
  551. unsigned long 
  552. writtenStringSize(tag,s)
  553. data_tag tag;
  554. char* s;
  555. {
  556.   unsigned long size;
  557.  
  558.   if (s == NULL)
  559.    return(0);
  560.  
  561.   size = writtenTagSize(tag);
  562.   size += writtenCompressedIntSize(size);
  563.   size += strlen(s);
  564.   return(size);
  565. }
  566.  
  567. /*----------------------------------------------------------------------*/
  568.  
  569. any* 
  570. longToAny(num)
  571. long num;
  572. /* a convienience function */
  573. {
  574.   char s[40];
  575.  
  576.   sprintf(s,"%ld",num);
  577.   
  578.   return(stringToAny(s));
  579. }
  580.  
  581. /*----------------------------------------------------------------------*/
  582.  
  583. long
  584. anyToLong(a)
  585. any* a;
  586. /* a convienience function */
  587. {
  588.   long num;
  589.   char* str = NULL;
  590.   str = anyToString(a);
  591.   sscanf(str,"%ld",&num);       /* could check the result and return
  592.                                    an error */
  593.   s_free(str);
  594.   return(num);
  595. }
  596.  
  597. /*----------------------------------------------------------------------*/
  598.  
  599. #define bitsPerByte     8
  600.  
  601. #ifdef ANSI_LIKE /* use ansi */
  602.  
  603. bit_map*
  604. makeBitMap(unsigned long numBits,...)
  605. /* construct and return a bitmap with numBits elements */
  606. {
  607.   va_list ap;
  608.   long i,j;
  609.   bit_map* bm = NULL;
  610.  
  611.   va_start(ap,numBits);
  612.   
  613.   bm = (bit_map*)s_malloc((size_t)sizeof(bit_map));
  614.   bm->size = (unsigned long)ceil((double)numBits / bitsPerByte); 
  615.   bm->bytes = (char*)s_malloc((size_t)bm->size);
  616.   
  617.   /* fill up the bits */
  618. #ifdef WIN32
  619.   for (i = 0; i < (long)(bm->size); i++) /* iterate over bytes */
  620. #else
  621.   for (i = 0; i < bm->size; i++) /* iterate over bytes */
  622. #endif
  623.     { char byte = 0;
  624.       for (j = 0; j < bitsPerByte; j++) /* iterate over bits */
  625. #ifdef WIN32
  626.         { if ((i * bitsPerByte + j) < (long)numBits)
  627. #else
  628.         { if ((i * bitsPerByte + j) < numBits)
  629. #endif
  630.             { boolean bit = false;
  631.               bit = (boolean)va_arg(ap,boolean); 
  632.               if (bit)
  633.                 { byte = byte | (1 << (bitsPerByte - j - 1));
  634.                 }
  635.             }
  636.           }
  637.       bm->bytes[i] = byte;
  638.     }
  639.  
  640.   va_end(ap);
  641.   return(bm);
  642. }
  643.  
  644. #else /* use K & R */
  645.  
  646. bit_map*
  647. makeBitMap(va_alist)
  648. va_dcl
  649. /* construct and return a bitmap with numBits elements */
  650. {
  651.   va_list ap;
  652.   long i,j;
  653.   unsigned long numBits;
  654.   bit_map* bm = (bit_map*)s_malloc((size_t)sizeof(bit_map));
  655.  
  656.   va_start(ap);
  657.   
  658.   numBits = va_arg(ap,unsigned long);
  659.  
  660.   bm->size = (unsigned long)ceil((double)numBits / bitsPerByte);
  661.   
  662.   bm->bytes = (char*)s_malloc((size_t)bm->size);
  663.   
  664.   /* fill up the bits */
  665.   for (i = 0; i < bm->size; i++) /* iterate over bytes */
  666.     { char byte = 0;
  667.       for (j = 0; j < bitsPerByte; j++) /* iterate over bits */
  668.         { if ((i * bitsPerByte + j) < numBits)
  669.             { boolean bit;
  670.               bit = (boolean)va_arg(ap,int); /* really boolean, but this 
  671.                                                 is how it is passed on stack */
  672.               if (bit)
  673.                 { byte = byte | (1 << (bitsPerByte - j - 1));
  674.                 }
  675.             }
  676.           }
  677.       bm->bytes[i] = byte;
  678.     }
  679.  
  680.   va_end(ap);
  681.  
  682.   return(bm);
  683. }
  684.  
  685. #endif 
  686.  
  687. /*----------------------------------------------------------------------*/
  688.  
  689. void
  690. freeBitMap(bm)
  691. bit_map* bm;
  692. /* destroy a bit map created by makeBitMap() */
  693. {
  694.   s_free(bm->bytes);
  695.   s_free(bm);
  696. }
  697.  
  698. /*----------------------------------------------------------------------*/
  699.  
  700. /* use this routine to interpret a bit map.  pos specifies the bit 
  701.    number.  bit 0 is the Leftmost bit of the first byte.  
  702.    Could do bounds checking.
  703.  */
  704.  
  705. boolean
  706. bitAtPos(pos,bm)
  707. long pos;
  708. bit_map* bm;
  709. {
  710. #ifdef WIN32
  711.   if (pos > (long)(bm->size*bitsPerByte))
  712. #else
  713.   if (pos > bm->size*bitsPerByte)
  714. #endif
  715.     return false;
  716.   else
  717.     return((bm->bytes[(pos / bitsPerByte)] & 
  718.             (0x80>>(pos % bitsPerByte))) ?
  719.            true : false);
  720. }
  721.  
  722. /*----------------------------------------------------------------------*/
  723.  
  724. char*
  725. writeBitMap(bm,tag,buffer,len)
  726. bit_map* bm;
  727. data_tag tag;
  728. char* buffer;
  729. long* len;
  730. /* write a bitmap + type and size info */
  731.   return(writeAny((any*)bm,tag,buffer,len));
  732. }
  733.  
  734. /*----------------------------------------------------------------------*/
  735.  
  736. char*
  737. readBitMap(bm,buffer)
  738. bit_map** bm;
  739. char* buffer;
  740. /* read a bitmap + type and size info */
  741.   return(readAny((any**)bm,buffer));
  742. }
  743.  
  744. /*----------------------------------------------------------------------*/
  745.  
  746. char* 
  747. writeByte(byte,buf,len)
  748. unsigned long byte;
  749. char* buf;
  750. long* len;
  751. {
  752.   CHECK_FOR_SPACE_LEFT(1L,len);
  753. #ifdef WIN32
  754.   buf[0] = (char)(byte & 0xFF); /* we really only want the first byte */
  755. #else
  756.   buf[0] = byte & 0xFF; /* we really only want the first byte */
  757. #endif
  758.   return(buf + 1);
  759. }
  760.  
  761. /*----------------------------------------------------------------------*/
  762.  
  763. char* 
  764. readByte(byte,buf)
  765. unsigned char* byte;
  766. char* buf;
  767. {
  768.   *byte = buf[0];
  769.   return(buf + 1);
  770. }
  771.  
  772. /*----------------------------------------------------------------------*/
  773.  
  774. char* 
  775. writeBoolean(flag,buf,len)
  776. boolean flag;
  777. char* buf;
  778. long* len;
  779. {
  780.   return(writeByte(flag,buf,len));
  781. }
  782.  
  783. /*----------------------------------------------------------------------*/
  784.  
  785. char* 
  786. readBoolean(flag,buffer)
  787. boolean* flag;
  788. char* buffer;
  789. {
  790.   unsigned char byte;
  791.   char* buf = readByte(&byte,buffer);
  792.   *flag = (byte == true) ? true : false;
  793.   return(buf);
  794. }
  795.  
  796. /*----------------------------------------------------------------------*/
  797.  
  798. char*
  799. writePDUType(pduType,buf,len)
  800. pdu_type pduType;
  801. char* buf;
  802. long* len;
  803. /* PDUType is a single byte */
  804. {
  805.   return(writeBinaryInteger((long)pduType,(unsigned long)1,buf,len));
  806.  
  807. /*----------------------------------------------------------------------*/
  808.  
  809. char*
  810. readPDUType(pduType,buf)
  811. pdu_type* pduType;
  812. char* buf;
  813. /* PDUType is a single byte */
  814. {
  815.   return(readBinaryInteger((long*)pduType,(unsigned long)1,buf));
  816.  
  817. /*----------------------------------------------------------------------*/
  818.  
  819. pdu_type
  820. peekPDUType(buf)
  821. char* buf;
  822. /* read the next pdu without advancing the buffer, Note that this 
  823.    function is to be used on a buffer that is known to contain an
  824.    APDU.  The pdu_type is written HEADER_LEN bytes into the buffer
  825.  */
  826. {
  827.   pdu_type pdu;
  828.   readPDUType(&pdu,buf + HEADER_LEN);
  829.   return(pdu);
  830. }
  831.  
  832. /*----------------------------------------------------------------------*/
  833.  
  834. #define BINARY_INTEGER_BYTES    sizeof(long) /* the number of bytes used by
  835.                                                 a "binary integer" */
  836. char*
  837. writeBinaryInteger(num,size,buf,len)
  838. long num;
  839. unsigned long size;
  840. char* buf;
  841. long* len;
  842. /* write out first size bytes of num - no type info
  843.   XXX should this take unsigned longs instead ???  */
  844. {
  845.   long i;
  846.   char byte;
  847.  
  848.   if (size < 1 || size > BINARY_INTEGER_BYTES)
  849.     return(NULL);               /* error */
  850.  
  851. #ifdef WIN32
  852.   CHECK_FOR_SPACE_LEFT((long)size,len);
  853. #else
  854.   CHECK_FOR_SPACE_LEFT(size,len);
  855. #endif
  856.  
  857.   for (i = size - 1; i >= 0; i--)
  858.     { byte = (char)(num & 255);
  859.       buf[i] = byte;
  860.       num = num >> bitsPerByte; /* don't and here */
  861.     }
  862.  
  863.   return(buf + size);
  864. }
  865.  
  866. /*----------------------------------------------------------------------*/
  867.  
  868. char*
  869. readBinaryInteger(num,size,buf)
  870. long* num;
  871. unsigned long size;
  872. char* buf;
  873. /* read in first size bytes of num - no type info
  874.   XXX this should take unsigned longs instead !!! */
  875. {
  876.   long i;
  877.   unsigned char byte;
  878.   if (size < 1 || size > BINARY_INTEGER_BYTES)
  879.     return(buf);                /* error */
  880.   *num = 0;
  881. #ifdef WIN32
  882.   for (i = 0; i < (long)size; i++)
  883. #else
  884.   for (i = 0; i < size; i++)
  885. #endif
  886.     { byte = buf[i];
  887.       *num = *num << bitsPerByte;
  888.       *num += byte;
  889.     }
  890.   return(buf + size);
  891. }
  892.  
  893. /*----------------------------------------------------------------------*/
  894.  
  895. unsigned long 
  896. writtenCompressedBinIntSize(num)
  897. long num;
  898. /* return the number of bytes needed to represent the value num.
  899.    currently limited to max of 4 bytes 
  900.    Only compresses for positive nums - negatives get whole 4 bytes
  901.  */
  902. {
  903.   if (num < 0L)
  904.     return(4);
  905.   else if (num < 256L)          /* 2**8 */
  906.     return(1);
  907.   else if (num < 65536L)        /* 2**16 */
  908.     return(2);
  909.   else if (num < 16777216L)     /* 2**24 */
  910.     return(3);
  911.   else
  912.     return(4);
  913. }
  914.  
  915. /*----------------------------------------------------------------------*/
  916.  
  917. char*
  918. writeNum(num,tag,buffer,len)
  919. long num;
  920. data_tag tag;
  921. char* buffer;
  922. long* len;
  923. /* write a binary integer + size and tag info */
  924. {
  925.   char* buf = buffer;
  926.   long size = writtenCompressedBinIntSize(num);
  927.   
  928.   if (num == UNUSED)
  929.     return(buffer);
  930.     
  931.   buf = writeTag(tag,buf,len);
  932.   buf = writeCompressedInteger(size,buf,len); 
  933.   buf = writeBinaryInteger(num,(unsigned long)size,buf,len); 
  934.   return(buf);
  935. }
  936.  
  937. /*----------------------------------------------------------------------*/
  938.  
  939. char*
  940. readNum(num,buffer)
  941. long* num;
  942. char* buffer;
  943. /* read a binary integer + size and tag info */
  944. {
  945.   char* buf = buffer;
  946.   data_tag tag;
  947.   unsigned long size;
  948.   unsigned long val;
  949.   
  950.   buf = readTag(&tag,buf);
  951.   buf = readCompressedInteger(&val,buf);
  952.   size = (unsigned long)val;
  953.   buf = readBinaryInteger(num,size,buf);
  954.   return(buf);
  955. }
  956.  
  957. /*----------------------------------------------------------------------*/
  958.  
  959. unsigned long 
  960. writtenNumSize(tag,num)
  961. data_tag tag;
  962. long num;
  963. {
  964.   long dataSize = writtenCompressedBinIntSize(num);
  965.   long size;
  966.   
  967.   size = writtenTagSize(tag); /* space for the tag */
  968.   size += writtenCompressedIntSize(dataSize); /* space for the size */
  969.   size += dataSize; /* space for the data */
  970.   
  971.   return(size);
  972. }
  973.  
  974. /*----------------------------------------------------------------------*/
  975.  
  976. typedef void (voidfunc)();
  977.  
  978. void
  979. doList(list,func)
  980. void** list;
  981. voidfunc *func;
  982. /* call func on each element of the NULL terminated list of pointers */
  983. {
  984.   register long i;
  985.   register void* ptr = NULL;
  986.   if (list == NULL)
  987.     return;
  988.   for (i = 0,ptr = list[i]; ptr != NULL; ptr = list[++i])
  989.     (*func)(ptr);
  990. }
  991.  
  992. /*----------------------------------------------------------------------*/
  993.  
  994. char* 
  995. writeProtocolVersion(buf,len)
  996. char* buf;
  997. long* len;
  998. /* write a bitmap describing the protocols available */
  999. {
  1000.   static bit_map* version = NULL;
  1001.  
  1002.   if (version == NULL)
  1003.    { version = makeBitMap((unsigned long)1,true); /* version 1! */
  1004.    }
  1005.     
  1006.   return(writeBitMap(version,DT_ProtocolVersion,buf,len));
  1007. }
  1008.  
  1009. /*----------------------------------------------------------------------*/
  1010.  
  1011. char*
  1012. defaultImplementationID()
  1013. {
  1014.   static char   ImplementationID[] = "TMC";
  1015.   return(ImplementationID);
  1016. }
  1017.  
  1018. /*----------------------------------------------------------------------*/
  1019.  
  1020. char*
  1021. defaultImplementationName()
  1022. {
  1023.   static char ImplementationName[] = "Thinking Machines Corporation Z39.50";
  1024.   return(ImplementationName);
  1025. }
  1026.  
  1027. /*----------------------------------------------------------------------*/
  1028.  
  1029. char*
  1030. defaultImplementationVersion()
  1031. {
  1032.   static char   ImplementationVersion[] = "2.0A";
  1033.   return(ImplementationVersion);
  1034. }
  1035.  
  1036. /*----------------------------------------------------------------------*/
  1037.  
  1038.